﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PMatch.Formats.SequenceSample;

namespace seqsplit
{
	class Program
	{
		static void Main(string[] args)
		{
			ExecSettings settings;
			ParseArguments(args, out settings);
			try
			{
				Execute(settings);
			}
			catch (Exception ex)
			{
				var eex = ex;
				do
				{
					Console.Error.WriteLine(ex.Message + "\n");
				} while ((eex = eex.InnerException) != null);
			}
		}

		private static void Execute(ExecSettings settings)
		{
			var ifile = samples.LoadFromFile(settings.Input);

			var pSamples = ifile.positive;
			var nSamples = ifile.negative;
			var pCount = pSamples.Count();
			var nCount = nSamples.Count();
			var totalCount = ifile.Count;

			Console.WriteLine("Input Positive: {0}", pCount);
			Console.WriteLine("Input Negative: {0}", nCount);
			Console.WriteLine("Input Total: {0}", totalCount);

			var rnd = settings.Random ? (new Random()) : null;
			var outs = settings.Percent.HasValue ?
				ifile.SplitDataset(rnd, settings.Percent.Value) :
				ifile.SplitDataset(rnd, settings.Count.Value);
			var output1 = outs[0];
			var output2 = outs[1];

			var positiveOutput1 = output1.positive.Count;
			var positiveOutput2 = output2.positive.Count;
			var negativeOutput1 = output1.negative.Count;
			var negativeOutput2 = output2.negative.Count;

			Console.WriteLine("Output 1: {0} samples (p:{1} + n:{2})", output1.Count, positiveOutput1, negativeOutput1);
			Console.WriteLine("Output 2: {0} samples (p:{1} + n:{2})", output2.Count, positiveOutput2, negativeOutput2);

			output1.SaveToFile(settings.Output1);
			output2.SaveToFile(settings.Output2);
		}

		private static void ParseArguments(string[] args, out ExecSettings settings)
		{
			if (args.Length < 4)
			{
				ShowUsage();
				Environment.Exit(255);
			}

			settings = new ExecSettings();
			settings.Input = args[0];
			settings.Output1 = args[1];
			settings.Output2 = args[2];

			var tags = args.Skip(3);

			const string COUNT_PARAM = "-c=";
			const string PERCENTAGE_PARAM = "-p=";
			const string RANDOM_PARAM = "-r";
			const string SEED_PARAM = "-s=";

			foreach (var tag in tags)
			{
				if (tag.StartsWith(COUNT_PARAM))
				{
					var value = int.Parse(tag.Substring(COUNT_PARAM.Length));
					settings.Count = value;
				}
				else if (tag.StartsWith(PERCENTAGE_PARAM))
				{
					var value = decimal.Parse(tag.Substring(PERCENTAGE_PARAM.Length));
					settings.Percent = value;
				}
				else if (tag.StartsWith(SEED_PARAM))
				{
					var value = int.Parse(tag.Substring(SEED_PARAM.Length));
					settings.Seed = value;
				}
				else if (tag == RANDOM_PARAM)
				{
					settings.Random = true;
				}
				else
				{
					Console.WriteLine("Invalid tag \"{0}\"", tag);
					Environment.Exit(255);
				}
			}

		}

		/// <summary>
		/// Muestra como se usa el programa por la consola
		/// </summary>
		private static void ShowUsage()
		{
			var help =
@"seqsplit splits a dataset using count or percentage requirement

	seqsplit input output1 output2 {-c=COUNT|-p=PERCENTAGE} -s=SEED [-r]

	input:         Conjunto de muetras de entrada 
	output1:       conjunto separado de tamaño COUNT o PERCENTAGE*length/100
	output2:       complemento del conjunto separado

	-c=COUNT       Tamaño del coujunto separado de salida
	-p=PERCENTAGE  Tamaño del conjunto separado de salida expresado en forma
	               porcentual (0.0 - 100.0)
	-r             Realiza la separacion en forma aleatoria
	-s=SEED        Semilla usada para la separación aleatoria de 
								 conjuntos, solo tiene efecto cuando se ha usado -r
";
			Console.WriteLine(help);
		}
	}

	class ExecSettings
	{
		public string Input { get; set; }
		public string Output1 { get; set; }
		public string Output2 { get; set; }
		public bool Random { get; set; }
		public decimal? Percent { get; set; }
		public int? Count { get; set; }
		public int? Seed { get; set; }
	}
}
